﻿using System;
using System.Collections;
using System.Runtime.CompilerServices;
using System.Threading;
using UnityEngine;
using UnityHFSM;

namespace moai_kun_v1 
{


public class MainPlayer : Actor,IDamageable
{
    #region Unity方法
    protected override void Awake()
    {
        base.Awake();
        InitCollider();
    }
    protected override void Update()
    {
        //if (CanMove()) 
        //{
        //    Move();
        //}
        //JumpMove();
    }

    

    protected override void OnDrawGizmos()
    {
        base.OnDrawGizmos();
        DrawAttackLine();
    }

    #endregion
    

    #region 移动
    [Header("移动能力")]
    [SerializeField] private float _moveSpeed = 3;
    private Vector2 _input;
   
    public bool CanMove()  
    {
        return OnGrounded&&!_death&&!_isJumping&&!_isAttacking;
    }
    public void Move(Vector2 input)
    {
        _input = input;
    }
    public void Move()
    {
        if (_input.x==0) 
        {
            Static();
        }
        else 
        {
            UpdateMove();
        }
    }
    public void Static()
    {
        SetVelocityZero();
        PlayAnim("idle");
    }
    public void UpdateMove()
    {
        PlayAnim("move");
        ShouldIfFlip((int)_input.x);
        SetVelocityX(_moveSpeed*_direction);
    }


    #endregion

    #region 跳
    [Header("跳能力")]
    [SerializeField] private float _jumpForce=10;
    [SerializeField] private Vector2 angle = new Vector2(1,1);
    [SerializeField] private float _waitJumpDetectTime=0.1f;
    private bool _isJumping;
    public bool IsJumping=> _isJumping;

    public bool CanJump()
    {
        return OnGrounded&&!_isJumping&&!_death;
    }
    public void Falling() 
    {
        PlayAnim("jump");
    }

    public void Jump()
    {
        if (!_isJumping) 
        {
            StartCoroutine(StartJumpDetect());
            _isJumping = true;
            
            if (_input.x == 0)
            {
                SetVelocityY(_jumpForce);
            }
            else
            {
                SetVelocity(_jumpForce, new Vector2(angle.x * _input.x, angle.y));
            }
        }
    }
    [SerializeField] private float _airforce=0.8f;
    [SerializeField] private float _dragForce=10;
    public void JumpMove()
    {
        if (_isJumping) 
        {
            ShouldIfFlip(_direction);
            SetVelocityX(_direction*_airforce*_dragForce);
        }
    }

    private IEnumerator StartJumpDetect()
    {
        yield return new WaitForSeconds(_waitJumpDetectTime);

        yield return new WaitUntil(() => OnGrounded);
        
        _isJumping = false;
    }
    #endregion

    #region 头锤
    [Header("攻击")]
    [SerializeField]private float _attackInterval;
    [SerializeField]private Transform _attackPos;
    [SerializeField] private LayerMask _damageMask;
    [SerializeField] private float _attackRadius=0.5f; 
    private bool _isAttacking;
    public bool IsAttacking=> _isAttacking;
    
    internal bool CanAttack()
    {
            throw new NotImplementedException();
    }
    public void Attack() 
    {
       
        PlayAnim("head_butting");
        _isAttacking = true;
        StartCoroutine(AttackDetectCoro());
        StartCoroutine(AttackEnd());
    }

    private IEnumerator AttackDetectCoro()
    {
        while (true) 
        {
            var hitInfo=Physics2D.OverlapCircle(_attackPos.position,_attackRadius,_damageMask);
            if (hitInfo != null) 
            {
                Debug.Log(hitInfo.name);
                var target=hitInfo.GetComponent<IDamageable>();
                AttackDetail detail=new AttackDetail();
                detail.Direction = _direction;
                target.TakeDamage(detail);
            }
            if (!_isAttacking) 
            {
                break;
            }
            yield return null;
        }
    }

    private IEnumerator AttackEnd()
    {
        yield return new WaitForSeconds(_attackInterval);
        _isAttacking= false;
    }

    private void DrawAttackLine()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(_attackPos.position, _attackRadius);
    }

    #endregion

    #region 推石头
    [SerializeField] private float _pushTime;
    private float _timer=0;

    public bool CanPush() 
    {
        return HasThingFont && OnGrounded;
    }
    public void Push() 
    {
        if (CanPush()) 
        {
            _timer += Time.deltaTime;
            if (_pushTime - _timer <= 0)
            {
                AudioManager.Instance.PlaySound(SoundType.Push);
                _timer = 0;
                LetStoneRoll();
            }
        }
        else 
        {
            _timer = 0;
        }
        
    }

    private void LetStoneRoll()
    {
        var stone=Obstacle.GetComponent<Stone>();
        if (stone) 
        {
            stone.Push(_direction);
        }
    }

    private IEnumerator PushCoro()
    {
        while (true) 
        {
            if (!HasThingFont) 
            {
                StopAllCoroutines();
            }
        }
    }
    #endregion

    #region 死亡
    [Header("死亡")]
    [SerializeField] private float _dieSpeed;
    [SerializeField] private float _waitInterval=0.2f;
    [SerializeField] private float _moveUpInterval=1f;
    private Collider2D _collider;
    private void InitCollider() 
    {
        _collider = GetComponent<Collider2D>();
    }

    private bool _death;
    

    public void TakeDamage(AttackDetail detail)
    {
        Die(null);
    }

    public void Die(Action afterDie)
    {
        _death = true;
        _collider.enabled = false;
        PlayAnim("die");
        StartCoroutine(DeathAnim(afterDie));
       
    }
    public bool CanDie()
    {
        return _death;
    }
    private IEnumerator DeathAnim(Action afterDie)
    {
        SetGravityScale(0);
        SetVelocityZero();
        yield return new WaitForSeconds(_waitInterval);
        SetVelocityY(_dieSpeed);
        yield return new WaitForSeconds(_moveUpInterval);
        GameSystem.Instance.ChangeGameState(State.Failure);
       
    }

    public void Hide()
    {
        this.gameObject.SetActive(false);
    }
    #endregion

    #region 其他
    public void Reset()
    {
        _death = false;
    }

        
        #endregion

    }
}
